/*
 * AtmelBasicDiag.cpp
 *
 * Created: 9/3/2020 9:35:40 PM
 * Author : Daniel
 */ 

#include <avr/io.h>
#include <avr/cpufunc.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include "Serial.h"

Serial serial = {
	0
};

static int serial_putchar( char c, FILE *f )
{
	serial_putonechar( c, fdev_get_udata( f ) );
	return 0;
}

static int serial_getchar( FILE *f )
{
	return serial_readonechar( fdev_get_udata( f ) );
}

static FILE iostream = FDEV_SETUP_STREAM( serial_putchar, serial_getchar, _FDEV_SETUP_RW );

#define TESTPIN( pin, bit ) \
PORTA = PORTB = PORTC = PORTD = PORTF = PORTH = PORTJ = PORTK = 0b11111111; PORTG = 0b00111111; PORTE = 0b11111100; \
DDR ## pin = bit; PORT ## pin = (uint8_t) ~bit;   \
_NOP(); _NOP(); _NOP();                 \
if( PIN ## pin != (uint8_t) ~bit )      \
{                                       \
	printf_P( PSTR( "Pin " #pin " bit %02x is shorted to %02x\n" ), bit, PIN ## pin ); \
}                                       \
DDR ## pin = 0;

#define TESTPIN1A( pin, bit, adjacent, aval ) \
PORTA = PORTB = PORTC = PORTD = PORTF = PORTH = PORTJ = PORTK = 0b11111111; PORTG = 0b00111111; PORTE = 0b11111100; \
DDR ## pin = bit; PORT ## pin = (uint8_t) ~bit;    \
_NOP(); _NOP(); _NOP();                 \
if( PIN ## adjacent != aval )           \
{                                       \
	printf_P( PSTR( "Pin " #pin " bit %02x is shorted to " #adjacent " %02x\n" ), bit, PIN ## adjacent ); \
}                                       \
DDR ## pin = 0;


#define TESTPIN2A( pin, bit, adj1, adj2 ) \
PORTA = PORTB = PORTC = PORTD = PORTF = PORTH = PORTJ = PORTK = 0b11111111; PORTG = 0b00111111; PORTE = 0b11111100; \
DDR ## pin = bit; PORT ## pin = (uint8_t) ~bit;    \
_NOP(); _NOP(); _NOP();                 \
if( PIN ## adj1 != 0b11111111 )         \
{                                       \
	printf_P( PSTR( "Pin " #pin " bit %02x is shorted to " #adj1 "\n" ), bit ); \
}                                       \
if( PIN ## adj2 != 0b11111111 )         \
{                                       \
	printf_P( PSTR( "Pin " #pin " bit %02x is shorted to " #adj2 "\n" ), bit ); \
}                                       \
DDR ## pin = 0;

#define TESTPINSA( pin, bit, adjacent ) \
PORTA = PORTB = PORTC = PORTD = PORTF = PORTH = PORTJ = PORTK = 0b11111111; PORTG = 0b00111111; PORTE = 0b11111100; \
DDR ## pin = bit; PORT ## pin = (uint8_t) ~bit;    \
_NOP(); _NOP(); _NOP();                 \
if( PIN ## adjacent != 0b11111111 )     \
{                                       \
	printf_P( PSTR( "Pin " #pin " bit %02x is shorted to " #adjacent "\n" ), bit ); \
}                                       \
if( PIN ## pin != (uint8_t) ~bit )      \
{                                       \
	printf_P( PSTR( "Pin " #pin " bit %02x is shorted to %02x\n" ), bit, PIN ## pin ); \
}                                       \
DDR ## pin = 0;

int main(void)
{
	serial_init( 115200, &serial );
	fdev_set_udata( &iostream, &serial );
	stdout = &iostream;
	stdin = stdout;

	printf( "Test start\n" );

	DDRA = 0;
	DDRB = 0;
	DDRC = 0;
	DDRD = 0;
	DDRE = 0b00000010;
	DDRF = 0;
	DDRG = 0;
	DDRH = 0;
	DDRJ = 0;
	DDRL = 0;
	SPCR = 0;

    PORTA = PORTB = PORTC = PORTD = PORTF = PORTH = PORTJ = PORTK = 0b11111111; PORTG = 0b00111111; PORTE = 0b11111100;
	
	DDRG = 0b00100000; PORTG = 0b00011111;
	_NOP(); _NOP(); _NOP();
	if( PINE != 0b11111101 )
	{
		DDRG = 0;
		printf_P( PSTR( "Pin G is shorted to UART\n") );
	}

	DDRE = 0b000000110; PORTE = 0b11111000;
	_NOP(); _NOP(); _NOP();
	if( ( PINE & 0b11111100 ) != 0b11111000 )
	{
		printf_P( PSTR( "Port E bit 04 is shorted to %02x\n" ), PINE );
	}
	printf_P( PSTR( "Port E bit 04 is OK\n") );
	DDRE = 0b00000010;
	
	DDRE = 0b00010010; PORTE = 0b11101100;
	_NOP(); _NOP(); _NOP(); _NOP(); _NOP(); _NOP(); _NOP(); _NOP();
	if( ( PINE & 0b11111100 ) != 0b11101100 )
	{
		printf_P( PSTR( "Port E bit 10 is shorted to %02x\n" ), PINE );
	}
	DDRE = 0b00000010;

	
	DDRE = 0b01000010; PORTE = 0b10111100;
	_NOP(); _NOP(); _NOP(); _NOP(); _NOP(); _NOP(); _NOP(); _NOP();
	if( ( PINE & 0b11111100 ) != 0b10111100 )
	{
		printf_P( PSTR( "Port E bit 40 is shorted to %02x\n" ), PINE );
	}
	DDRE = 0b00000010;

	TESTPIN( H, 0b00000010 );
	TESTPIN( H, 0b00001000 );
	TESTPIN( H, 0b00100000 );
	TESTPINSA( B, 0b00000001, H );
	TESTPIN( B, 0b00000100 );
	TESTPIN( B, 0b00010000 );
	TESTPIN( B, 0b01000000 );

	TESTPIN1A( B, 0b10000000, H, 0b11111111 );
	
	PORTA = PORTB = PORTC = PORTD = PORTF = PORTH = PORTJ = PORTK = 0b11111111; PORTG = 0b00111111; PORTE = 0b11111100;
	DDRG = 0b00001000; PORTG = 0b00110111;
	_NOP(); _NOP(); _NOP();
	if( PINH != 0b11111111 )
	{
		printf_P( PSTR( "Pin G bit %02x is shorted to H\n" ), 0b00001000 );
	}
	if( PING != 0b00110111 )
	{
		printf_P( PSTR( "Pin G bit %02x is shorted to %02x\n" ), 0b00001000, PING );
	}
	DDRG = 0;
	
	TESTPIN( L, 0b00000010 );
	TESTPIN( L, 0b00001000 );
	TESTPIN( L, 0b00100000 );
	TESTPINSA( L, 0b10000000, D );
	TESTPIN( D, 0b00000010 );
	TESTPIN( D, 0b00001000 );
	TESTPIN( D, 0b00100000 );
	TESTPIN( D, 0b10000000 );
	
PORTA = PORTB = PORTC = PORTD = PORTF = PORTH = PORTJ = PORTK = 0b11111111; PORTG = 0b00111111; PORTE = 0b11111100;
DDRG = 0b00000010; PORTG = 0b00111101;
_NOP(); _NOP(); _NOP();
if( PINC != 0b11111111 )
{
	printf_P( PSTR( "Pin G bit %02x is shorted to C\n" ), 0b00000010 );
}
if( PING != 0b00111101 )
{
	printf_P( PSTR( "Pin G bit %02x is shorted to %02x\n" ), 0b00000010, PING );
}
DDRG = 0;

	TESTPIN( C, 0b00000010 );
	TESTPIN( C, 0b00001000 );
	TESTPIN( C, 0b00100000 );
	TESTPIN( C, 0b10000000 );
	TESTPIN( J, 0b00000010 );
	TESTPIN( J, 0b00001000 );
	TESTPIN( J, 0b00100000 );
	TESTPIN2A( G, 0b00000100, J, A );
	TESTPIN( A, 0b01000000 );
	TESTPIN( A, 0b00010000 );

	TESTPIN( A, 0b00000010 );
	TESTPIN1A( J, 0b10000000, A, 0b11111111 );
	TESTPIN( K, 0b01000000 );
	TESTPIN( K, 0b00010000 );
	TESTPIN( K, 0b00000100 );
	TESTPINSA( K, 0b00000001, F );
	TESTPIN( F, 0b01000000 );
	TESTPIN( F, 0b00010000 );
	TESTPIN( F, 0b00000100 );
	TESTPIN( F, 0b00000001 );
	
	printf_P( PSTR( "All tests done\n" ) );

    /* Replace with your application code */
    while (1) 
    {
    }
}

